import re

from django.db import models, transaction, DatabaseError
from django.db.models import Q
from django.utils import timezone


class TeacherChangeClassRecord(models.Model):
    # 当前学期
    term = models.CharField(max_length=100, verbose_name="学期", blank=True)
    # 关联教师
    teacher_id = models.CharField(max_length=100, verbose_name="教师账号", blank=True)
    teacher_name = models.CharField(max_length=100, verbose_name="教师姓名", blank=True)
    # 调课类型
    TYPE_CHOICES = [('调课', '调课'), ('停课', '停课'), ('补课', '补课'), ('代课', '代课'), ('拆/合班', '拆/合班'), ]
    type = models.CharField(max_length=100, choices=TYPE_CHOICES, verbose_name="调课类型", blank=True)
    # 临时还是长期调课
    change_type = models.CharField(max_length=100, choices=[("临时", "临时"), ("长期", "长期")],
                                   verbose_name="调课时限", blank=True)
    # 课程名
    course_name = models.CharField(max_length=100, verbose_name="课程名", blank=True)

    # 涉及班级
    original_class = models.CharField(max_length=100, verbose_name="原课程班级", blank=True)
    # 原课程周次
    # week_CHOICES = [('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'),
    #                 ('8', '8'), ('9', '9'), ('10', '10'),
    #                 ('11', '11'), ('12', '12'),
    #                 ('13', '13'), ('14', '14'), ('15', '15'), ('16', '16'), ('17', '17'), ]
    original_week = models.CharField(max_length=100, verbose_name="原课程周次",
                                     blank=True)
    # 原课程--星期节次
    original_class_time = models.CharField(max_length=100, verbose_name="原星期/节次", blank=True)
    # 原上课教室
    original_room = models.CharField(max_length=100, verbose_name="原上课教室", blank=True)
    # 新课程安排
    new_week = models.CharField(max_length=100, verbose_name="新课程周次", blank=True, null=True)
    # 新课程--节次
    new_class_time = models.CharField(max_length=100, verbose_name="新星期/节次", blank=True, null=True)
    # 新上课教室
    new_room = models.CharField(max_length=100, verbose_name="新上课教室", blank=True, null=True)

    # 调课原因类型
    REASON_CHOICES = [('因公', '因公'), ('因私', '因私'), ]
    reason_type = models.CharField(max_length=100, choices=REASON_CHOICES, verbose_name="调课原因类型", blank=True)
    # 调课具体原因
    reason = models.TextField(verbose_name="调课原因", blank=True)

    # 调课状态
    STATUS_CHOICES = [('已批准', '已批准'), ('待审批', '待审批'), ('已拒绝', '已拒绝'), ]
    revstatus = models.CharField(max_length=100, choices=STATUS_CHOICES, default='待审批', verbose_name="调课状态")
    #

    # 记录时间
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间", blank=True)
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间", blank=True)
    # 附件
    attachment = models.FileField(upload_to='CourseAdjustmentManagement',  # 上传目录
                                  verbose_name='附件', help_text='建议仅上传pdf/zip', blank=True, null=True,
                                  max_length=1000  # 设置数据库中可以存储的最大字符数
                                  )

    class Meta:
        verbose_name = "教师调课记录"
        verbose_name_plural = "教师调课记录"

    # 设置一个方法用于查找new_room是有空，即不同数据的 new_class_time的时间段与new_room 不得冲突。
    def find_conflict_records(self):
        # 初始过滤term
        conflict_records = TeacherChangeClassRecord.objects.filter(term=self.term)

        try:
            # 尝试将self.new_week转换为整数
            week_value = int(self.new_week)
            # 正则表达式匹配"start-end"格式
            range_pattern = re.compile(r'^(\d+)-(\d+)$')

            # 筛选出直接匹配的记录以及范围包含week_value的记录
            filtered_records = conflict_records.filter(
                Q(new_week__exact=self.new_week) |  # 直接匹配
                Q(new_week__regex=range_pattern.pattern)  # 匹配"start-end"格式
            )

            final_conflicts = []
            for record in filtered_records:
                if record.new_week == self.new_week:
                    # 完全匹配的情况
                    final_conflicts.append(record)
                else:
                    # 检查"start-end"格式的范围
                    match = range_pattern.match(record.new_week)
                    if match:
                        start, end = map(int, match.groups())
                        if start <= week_value <= end:
                            final_conflicts.append(record)

            return final_conflicts

        except ValueError:
            # 如果self.new_week不是纯数字，则只进行完全匹配
            return conflict_records.filter(new_week=self.new_week)

    def check_new_room(self):
        # day, int(start_class), int(end_class)
        # 筛选出所有new_week=week 并且 term相同的数据
        conflict_records = self.find_conflict_records()
        for record in conflict_records:
            # 避免同一条数据
            if record.id == self.id:
                continue
            if record.revstatus == '已拒绝':
                continue
            if record.new_week == '' or record.new_class_time == '':
                continue
            # 判断是否是同一个教室
            if record.new_room == self.new_room:
                # 判断时间段是否冲突
                self_day, class_range_str = self.new_class_time.split('/')
                self_start_class, self_end_class = class_range_str.split('-')

                record_day, record_class_range_str = record.new_class_time.split('/')
                record_start_class, record_end_class = record_class_range_str.split('-')
                if self_day == record_day:
                    if int(self_end_class) < int(record_start_class) or (int(self_start_class) > int(record_end_class)):
                        pass
                    else:
                        return False
        return True

    # 查询选择的教室是不是原本就有课
    def check_org_room(self):
        reports = ClassroomSchedule.objects.filter(term=self.term, week=self.new_week, classroom_name=self.new_room)
        self_day, class_range_str = self.new_class_time.split('/')
        self_start_class, self_end_class = class_range_str.split('-')
        for report in reports:
            record_day, record_class_range_str = report.new_class_time.split('/')
            record_start_class, record_end_class = record_class_range_str.split('-')
            # 如果星期也相等则比较时间
            if self_day == record_day:
                if int(self_end_class) < int(record_start_class) or (int(self_start_class) > int(record_end_class)):
                    pass
                else:
                    return False

        return True

    def save(self, *args, **kwargs):
        adding = self.pk is None  # 判断是否为新实例
        if adding:
            self.created_at = timezone.now()
            self.updated_at = timezone.now()
        else:
            self.updated_at = timezone.now()
        if self.type == '停课':
            self.new_class_time = ''
            self.new_room = ''
            self.new_week = ''
        elif self.type == '代课':
            # 代课的安排不能改变
            pass
        elif self.type == '调课' or self.type == '补课':
            if self.new_class_time == '' or self.new_room == '' or self.new_week == '':
                raise Exception("你是调补课，请认真填写你的新上课安排（新时间 新教室 新周次）")
            if not self.check_new_room():
                raise Exception(
                    "该教室已在系统中被人申请，请前往空教室查询功能查询空教室")  # 正确，Exception 是 BaseException 的子类"该房间已经被占用"
        super().save(*args, **kwargs)

    @classmethod
    def update_record_safely(cls, record_id, **kwargs):
        try:
            with transaction.atomic():
                # 使用select_for_update()来锁定记录
                record = cls.objects.select_for_update().get(id=record_id)
                # 更新记录
                for key, value in kwargs.items():
                    setattr(record, key, value)
                record.save()
                # 返回更新后的记录
                return record
        except cls.DoesNotExist:
            # 记录不存在，可以返回None或抛出自定义异常
            raise Exception("你要更新的记录不存在")
        except DatabaseError as e:
            # 发生数据库错误，可以记录日志，返回错误信息或抛出异常
            # 例如: logger.error(f"Database error occurred: {e}")
            raise Exception("数据发生错误: {}".format(e))


# 创建一个模型去记录每个教室的课程表
class ClassroomSchedule(models.Model):
    class Meta:
        verbose_name = "教室课程表"
        verbose_name_plural = "教室课程表"
        unique_together = ('classroom_name', 'term', 'week', 'new_class_time')

    classroom_name = models.CharField(max_length=100, verbose_name="教室名")

    term = models.CharField(max_length=100, verbose_name="学期", blank=True)
    # 周次
    week_CHOICES = [('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'),
                    ('8', '8'), ('9', '9'), ('10', '10'),
                    ('11', '11'), ('12', '12'),
                    ('13', '13'), ('14', '14'), ('15', '15'), ('16', '16'), ('17', '17'), ]
    week = models.CharField(max_length=100, choices=week_CHOICES, verbose_name="周次")
    # 新课程--节次
    new_class_time = models.CharField(max_length=100, verbose_name="星期/节次", blank=True)
    # 课程号
    course_id = models.CharField(max_length=100, verbose_name="课程号", blank=True)
    # 课程名
    course_name = models.CharField(max_length=100, verbose_name="课程名", blank=True)
    # 任课教师账号
    teacher_id = models.CharField(max_length=100, verbose_name="教师账号", blank=True)
    # 任课教师名
    teacher_name = models.CharField(max_length=100, verbose_name="教师名", blank=True)
    # 课程类型  原课程 调补课 其它占用
    type_CHOICES = [('原课程', '原课程'), ('调补课', '调补课'), ('其它占用', '其它占用')]
    type = models.CharField(max_length=100, choices=type_CHOICES, verbose_name="课程类型", blank=True, default='原课程')
